#ifndef EPOLL_SERVER_H
#define EPOLL_SERVER_H

#include "EpollEvent.h"
#include "EpollCallbackInterface.h"

#include <ext/hash_map>
#include <ext/hash_set>
using namespace Util;

namespace Net{
    class EpollServer
    {
        public:
            typedef EpollCallbackInterface Callback;

        public:
            EpollServer();
            virtual ~EpollServer();

        public:
            virtual void RegisterFD(int fd, Callback* cb, int event_mask);
            virtual void RegisterFDForWrite(int fd, Callback *cb);
            virtual void RegisterFDForReadWrite(int fd, Callback *cb);
            virtual void RegisterFDForRead(int fd, Callback *cb);
            virtual void UnregisterFD(int fd);

            virtual void ModifyCallback(int fd, int event_mask);

            virtual void StopRead(int fd);
            virtual void StartRead(int fd);
            virtual void StopWrite(int fd);
            virtual void StartWrite(int fd);

            void HandleEvent(int fd, int event_mask);
            virtual void WaitForEventsAndExecuteCallback();

            virtual void SetFDReady(int fd, int events_mask_tofake);
            virtual void SetFDNotReady(int fd);
            virtual bool IsFDReady(int fd) const;
            size_t ReadyListSize() const;
            void VerifyReadyList() const;

            virtual void Wake();
            virtual void NumFDsRegistered() const;

            static string EventMaskToString(int event_mask);

        protected:
            virtual int GetFlags(int fd);
            virtual int SetFlags(int fd, int flags);
            virtual void SetNonBlocking(int fd);
            virtual int epoll_wait_imp(int epfd, 
                    struct epoll_event *events,
                    int max_events, int timeout_in_ms);

        protected:
            //EpollServer内部使用用于关联FD和Callback之类的结构体
            struct CallbackAndEventMask
            {
                CallbackAndEventMask();
                CallbackAndEventMask(EpollCallbackInterface *cb,
                        int fd, int event);

                //在hash_map里要使用这个==操作来判断数据
                bool operator == (const CallbackAndEventMask&  obj);


                mutable EpollCallbackInterface* callback;
                mutable LIST_ENTRY(CallbackAndEventMask) entry;
                //在EpollServer注册的FD
                int fd;
                //当前Callback所关注的事件mask
                mutable int event_mask;
                //epoll返回的事件mask
                mutable int events_asserted;
                //ready list中用来调用OnEvent时所使用的事件mask
                mutable int events_to_fake;
                mutable bool in_use

            };

            //用来做CallbackAndEventMask在hash_map里的hash函数
            struct CallbackAndEventMaskHash {
                size_t operator()(const CallbackAndEventMask& ) const 
            };

            typedef __gnu_cxx::hash_set<
                CallbackAndEventMask, CallbackAndEventMaskHash
                > FDToCallbackMap;

    };

    //============CallbackAndEventMask======================
    inline EpollServer::CallbackAndEventMask::CallbackAndEventMask()
        :callback(NULL),fd(-1),event_mask(0),events_asserted(0),
        events_to_fake(0),in_use(0)
    {
        entry.le_prev = entry.le_next = NULL;
    }

    inline EpollServer::CallbackAndEventMask::CallbackAndEventMask(
            EpollCallbackInterface *cb,int fd, int event)
        :callback(cb), fd(fd), event_mask(event_mask),
        events_asserted(0), events_to_fake(0),in_use(0)
    {
        entry.le_prev = entry.le_next = NULL;
    }

    inline bool EpollServer::CallbackAndEventMask::operator == (
            const CallbackAndEventMask&  obj)
    {
        return fd == obj.fd;
    }

    //============CallbackAndEventMaskHash==================
    inline size_t EpollServer::CallbackAndEventMaskHash::operator()
        (const CallbackAndEventMask& cb_and_eventmask) const 
    {
        return static_cast<size_t>(cb_and_eventmask.fd);
    }


    //=============EpollServer============================



}
#endif
